package com.easpeed.comon.utils

import com.easpeed.comon.bean.AppOperateBean
import com.easpeed.comon.bean.OtdrOriangeBean
import com.easpeed.user.bean.TcpBean
import com.google.gson.Gson
import net.jpountz.lz4.LZ4Factory
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.util.Arrays
import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
import kotlin.random.Random

/**
 * Created by bigyu on 2024/11/1 09:09
 * com.easpeed.user.bean
 */
public open class TcpData {


    var code: Int = 0

    var msg: String = ""

    var data: TcpBean? = null


    var commandStr: String = ""
    var bundleStr: String = ""

    var any: Any? = null
}

object TcpCode {

    //连接服务器成功
    const val SUCCESS = 1

    const val SUCCESS_SERVER = 2
    const val NEED_RECONNECT = 3

    //连接服务器失败
    const val FAILED = 0

}

object SendCommand {
    @JvmField
    val heartbeatCommand = byteArrayOf(0x01, 0x00) // 心跳命令

    @JvmField
    val errorCommand = byteArrayOf(0x01, 0x90.toByte()) // 异常指令

    @JvmField
    val changeChannelCommand = byteArrayOf(0x01, 0x11) // 通道切换相关

    @JvmField
    val changeDvsStateCommand = byteArrayOf(0x01, 0x12) // 开关DVS状态

    //设备端收到 表示请求事件表；用户端收到 表示收到事件表数据
    @JvmField
    val commandEventTable = byteArrayOf(0x01, 0x13) // 事件表数据

    //OtdrBean
    @JvmField
    val commandOTDRDataRequest = byteArrayOf(0x01, 0x14) // OTDR数据请求(用户索求)

    @JvmField
    val commandOTDRRedRequest = byteArrayOf(0x01, 0x35) // 开启指示红光(用户索求)

    @JvmField
    val commandEventThresholdRequest = byteArrayOf(0x01, 0x36) // 设置事件阈值

    //List<double[]>
    @JvmField
    val commandOTDRDataResponse = byteArrayOf(0x01, 0x15) // 设备OTDR数据回复（设备给与）

    //设备端 连上服务端后，如果有用户端，则服务器发送一个指令给设备端 01、00表示在线、离线
    //后续用户连上、断开，服务端同样发给设备端
    @JvmField
    val commandOnlineState = byteArrayOf(0x01, 0x16) // 设备收到用户上线情况提示

    //List<double[]>
    @JvmField
    val commandDvsDataRequest = byteArrayOf(0x01, 0x17) // 用户请求DVS数据（用户索求）

    //SendOrderEvent
    @JvmField
    val commandDvsDataResponse = byteArrayOf(0x01, 0x18) // 设备给与DVS数据回复（设备给与）

    //通用提示命令
    @JvmField
    val commandResponse = byteArrayOf(0x01, 0x19)

    /**
     * 用户操作app相关,数据类型 [AppOperateBean]
     */
    @JvmField
    val commandAppOperate = byteArrayOf(0x01, 0x20)

    /**
     *  用户上线后告诉服务端自己的名称  0x01 0x21  ,data=“设备名称”
     *  用户离线后服务端告诉设备离线  0x01 0x22  ,data=“设备名称”
     *  用户在线后服务端告诉设备在线  0x01 0x23  ,data=“设备名称”
     */
    @JvmField
    val commandUserOnlineOperate = byteArrayOf(0x01, 0x23)

    @JvmField
    val commandUserOfflineOperate = byteArrayOf(0x01, 0x22)

    @JvmField
    val commandUserNameOperate = byteArrayOf(0x01, 0x21)

    //实时寻峰事件点
    @JvmField
    val commandSsxfResponseOperate = byteArrayOf(0x01, 0x25)

    @JvmField
    val commandMatrixRequest = byteArrayOf(0x01, 0x26)

    @JvmField
    val commandMatrixResponse = byteArrayOf(0x01, 0x27)

    @JvmField
    val commandExpandResponse = byteArrayOf(0x01, 0x28)

    //同步隐藏的OTDR数据
    @JvmField
    val commandSyncHideOtdrData = byteArrayOf(0x01, 0x29)

    //同步余晖开关状态
    @JvmField
    val commandSyncYuhuiData = byteArrayOf(0x01, 0x30)

    //折线图选中状态
    @JvmField
    val commandSyncLineData = byteArrayOf(0x01, 0x31)

    //获取设备端电量
    @JvmField
    val commandSyncBattery = byteArrayOf(0x01, 0x32)
    //同步otdr设置
    @JvmField
    val commandSyncOTDRSetting = byteArrayOf(0x01, 0x33)
    //同步dvs设置
    @JvmField
    val commandSyncDVSSetting = byteArrayOf(0x01, 0x34)


    @JvmStatic
    fun commandToStr(command: ByteArray): String {
        return command.bytesToHex()
    }
}

fun isBigCommand(command: ByteArray): Boolean {
    if (command.contentEquals(SendCommand.commandOTDRDataResponse) || command.contentEquals(SendCommand.commandDvsDataResponse)) {
        return true
    }
    return false
}

object CommandReceiveData {
    @JvmField
    val openState = byteArrayOf(0x01) // 开关DVS状态

    @JvmField
    val closeState = byteArrayOf(0x00) // 开关DVS状态

    @JvmStatic
    fun commandToStr(command: ByteArray): String {

        return command.bytesToHex()
    }
}

object PackageLength {
    @JvmField
    val dataLength = 2 // 数据包长度描述
}

object TcpCommand {

    private val commandErrorMap = hashMapOf<String, String>()


    fun getError(code: String): String {
        if (commandErrorMap.isEmpty()) {
            commandErrorMap["01"] = "设备离线"
            commandErrorMap["02"] = "其他用户连接，无法建立连接"
        }


        return commandErrorMap[code] ?: ""
    }
}


// 将16进制字符串转换为字节数组
fun hexStringToByteArray(hexString: String): ByteArray {
    // 检查长度是否为偶数
    if (hexString.length % 2 != 0) {
        throw IllegalArgumentException("Hex string length must be even.")
    }

    val byteArray = ByteArray(hexString.length / 2)
    for (i in byteArray.indices) {
        val index = i * 2
        // 将每两个字符转换为一个字节
        byteArray[i] = hexString.substring(index, index + 2).toInt(16).toByte()
    }
    return byteArray
}


// 使用LZ4快速压缩
fun compressLZ4(data: ByteArray): ByteArray {
    val factory = LZ4Factory.fastestInstance()
    val compressor = factory.fastCompressor()
    val maxCompressedLength = compressor.maxCompressedLength(data.size)
    val compressed = ByteArray(maxCompressedLength)
    val compressedLength = compressor.compress(data, 0, data.size, compressed, 0, maxCompressedLength)
    return compressed.copyOf(compressedLength)
}

// 使用LZ4解压缩
fun decompressLZ4(compressedData: ByteArray, originalSize: Int): ByteArray {
    val factory = LZ4Factory.fastestInstance()
    val decompressor = factory.fastDecompressor()
    val restored = ByteArray(originalSize)
    decompressor.decompress(compressedData, 0, restored, 0, originalSize)
    return restored
}

fun generateRandomHexString(length: Int): String {
    val hexChars = "0123456789ABCDEF"
    val result = StringBuilder(length)

    repeat(length) {
        val randomChar = hexChars[Random.nextInt(hexChars.length)]
        result.append(randomChar)
    }

    return result.toString()
}

fun compressData(data: ByteArray): ByteArray {
    val byteArrayOutputStream = ByteArrayOutputStream()
    val gzipOutputStream = GZIPOutputStream(byteArrayOutputStream)
    try {
        gzipOutputStream.write(data)
        gzipOutputStream.close()
    } catch (e: IOException) {
        e.printStackTrace()
    }
    return byteArrayOutputStream.toByteArray()
}

fun decompressData(compressedData: ByteArray): ByteArray {
    val byteArrayInputStream = ByteArrayInputStream(compressedData)
    val gzipInputStream = GZIPInputStream(byteArrayInputStream)
    val byteArrayOutputStream = ByteArrayOutputStream()
    try {
        var byteRead: Int
        while (gzipInputStream.read().also { byteRead = it } != -1) {
            byteArrayOutputStream.write(byteRead)
        }
        gzipInputStream.close()
    } catch (e: IOException) {
        e.printStackTrace()
    }
    return byteArrayOutputStream.toByteArray()
}
